package cn.kgc.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.kgc.base.BaseInfoProperties;
import cn.kgc.entity.Industry;
import cn.kgc.excpetion.GraceException;
import cn.kgc.form.IndustryAddForm;
import cn.kgc.form.IndustryUpdateForm;
import cn.kgc.grace.result.GraceJSONResult;
import cn.kgc.grace.result.ResponseStatusEnum;
import cn.kgc.interceptor.JwtInterceptor;
import cn.kgc.service.IndustryService;
import cn.kgc.utils.RedisUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author k
 */
@RestController
@RequestMapping("/industry")
@Api(tags = "行业管理模块")
@Validated
@Slf4j
@SuppressWarnings("all")
public class IndustryController extends BaseInfoProperties {
    @Resource
    private IndustryService industryService;
    @Resource
    private RedisUtil redisUtil;

    @Resource
    private RedissonClient redissonClient;

    @Resource
    private RBloomFilter industryRBloomFilter;

    @GetMapping("/app/getThirdList3")
    @ApiOperation(value = "获得一级行业分类下的三级行业分类信息")
    public GraceJSONResult getThirdListByTopId3(String fatherId){
        String userId=  JwtInterceptor.userIds.get();
        if(StrUtil.isNotBlank(userId)) {
            Object o = redisUtil.get(INDUSTRY_ALL_PREFIX);
            List<Industry> list=null;
            if(o==null){ //如果缓存中没有数据,查询一级行业的信息放入到缓存中
                list = industryService.getTopIndustry();
                redisUtil.set(INDUSTRY_ALL_PREFIX,list);
            }else{
                list=(List<Industry>) o;
            }
            boolean flag= list.stream() .anyMatch(temp->temp.getId().equals(fatherId));
            if(!flag) {
                //如果缓存中没有一级行业id,直接返回空的集合
                return GraceJSONResult.ok(Collections.emptyList());
            }
            //如果缓存中有一级行业id,查询一级行业id下的三级行业信息
            Object data=redisUtil.get(INDUSTRY_TOP_PREFIX+fatherId);
            if(data!=null){
                return GraceJSONResult.ok(data);
            }
            //如果缓存中没有数据,需要上锁 从数据库中查询数据  .....
            return null;
        }
        return GraceJSONResult.errorMsg("没有权限操作");
    }


    @GetMapping("/app/getThirdList2")
    @ApiOperation(value = "获得一级行业分类下的三级行业分类信息")
    public GraceJSONResult getThirdListByTopId2(String fatherId){
        //获得登录的用户(求职者 招聘者)ID
        String userId= JwtInterceptor.userIds.get();
        if(StrUtil.isNotBlank(userId)) {
            List<Industry> list= Collections.emptyList();
            //如果用户请求的一级行业id不在布隆过滤器中,一级行业的id肯定就不存在,直接返回空的集合。
            if(!industryRBloomFilter.contains(fatherId)){
                return GraceJSONResult.ok(list);
            }
            //从缓存中获得一级行业分类下的三级行业信息
            Object data=redisUtil.get(INDUSTRY_TOP_PREFIX+fatherId);
            if(data!=null){
                //如果缓存中有数据就直接返回
                return GraceJSONResult.ok(data);
            }
            //如果缓存中没有数据,需要上锁 （如果查询行业id为1的三级行业信息  如果查询行业id为3的三级行业信息）
            RLock rLock= redissonClient.getLock("industry:lock:"+fatherId);
            try {
                //线程尝试获得锁,如果5s还没有获得锁,不在获得锁。直接返回false。
                //30s是上锁的时间,保证30s内业务代码能够执行完毕。
                if(rLock.tryLock(5,30,TimeUnit.SECONDS)){
                    data=redisUtil.get(INDUSTRY_TOP_PREFIX+fatherId);
                    if(data!=null){
                        return GraceJSONResult.ok(data);
                    }
                    //如果缓存中没有数据,需要从数据库中查询数据
                    list= industryService.getThirdIndustry(fatherId);
                    if(CollUtil.isEmpty(list)){
                        //如果查询的数据为空,则将空的值放入到缓存中,防止缓存穿透。指定过期时间。
                        redisUtil.set(INDUSTRY_TOP_PREFIX+fatherId,list,30, TimeUnit.SECONDS);
                    }else{
                        //如果查询的数据不为空,则将查询的数据放入到缓存中
                        redisUtil.set(INDUSTRY_TOP_PREFIX+fatherId,list);
                    }
                }else{
                    log.warn("请求超时,没有获得"+fatherId+"下的三级行业信息");
                }
            }catch (InterruptedException e) {  //如果等待的线程被中断,触发InterruptedException异常
                //设置当前线程的状态被中断
                Thread.currentThread().isInterrupted();
                log.error("当前线程被中断");
                return GraceJSONResult.ok(list);
            }finally{
                if(rLock.isHeldByCurrentThread()){
                    //如果当前线程持有锁,则释放锁
                    rLock.unlock();
                }
            }
            return GraceJSONResult.ok(list);
        }
        return GraceJSONResult.errorMsg("没有权限访问");
    }

    @GetMapping("/app/getThirdList")
    @ApiOperation(value = "获得一级行业分类下的三级行业分类信息")
    public GraceJSONResult getThirdListByTopId(String fatherId) {
       //获得登录的用户(求职者 招聘者)ID
       String userId=  JwtInterceptor.userIds.get();
       if(StrUtil.isNotBlank(userId)) {
            //从缓存中获得一级行业分类下的三级行业信息
            Object data=redisUtil.get(INDUSTRY_TOP_PREFIX+fatherId);
            if(data!=null){
                //如果缓存中有数据就直接返回
                return GraceJSONResult.ok(data);
            }
            //如果缓存中没有数据,需要上锁 （如果查询行业id为1的三级行业信息  如果查询行业id为3的三级行业信息）
            RLock rLock= redissonClient.getLock("industry:lock:"+fatherId);
            List<Industry> list= Collections.emptyList();
           try {
               //线程尝试获得锁,如果5s还没有获得锁,不在获得锁。直接返回false。
               //30s是上锁的时间,保证30s内业务代码能够执行完毕。
               if(rLock.tryLock(5,30,TimeUnit.SECONDS)){
                   data=redisUtil.get(INDUSTRY_TOP_PREFIX+fatherId);
                   if(data!=null){
                       return GraceJSONResult.ok(data);
                   }
                   //如果缓存中没有数据,需要从数据库中查询数据
                   list= industryService.getThirdIndustry(fatherId);
                   if(CollUtil.isEmpty(list)){
                       //如果查询的数据为空,则将空的值放入到缓存中,防止缓存穿透。指定过期时间。
                       redisUtil.set(INDUSTRY_TOP_PREFIX+fatherId,list,30, TimeUnit.SECONDS);
                   }else{
                       //如果查询的数据不为空,则将查询的数据放入到缓存中
                       redisUtil.set(INDUSTRY_TOP_PREFIX+fatherId,list);
                   }
               }else{
                   log.warn("请求超时,没有获得"+fatherId+"下的三级行业信息");
               }
           }catch (InterruptedException e) {  //如果等待的线程被中断,触发InterruptedException异常
               //设置当前线程的状态被中断
               Thread.currentThread().isInterrupted();
               log.error("当前线程被中断");
               return GraceJSONResult.ok(list);
           }finally{
               if(rLock.isHeldByCurrentThread()){
                   //如果当前线程持有锁,则释放锁
                   rLock.unlock();
               }
           }
           return GraceJSONResult.ok(list);
       }
       return GraceJSONResult.errorMsg("没有权限访问");
    }


    @GetMapping("/app/initTopList")
    @ApiOperation(value = "手机端获得一级行业分类的信息")
    public GraceJSONResult initTopListIndustry(){
        String userId = JwtInterceptor.userIds.get();
        if(StrUtil.isNotBlank(userId)) {
            String key=INDUSTRY_ALL_PREFIX;
            Object object= redisUtil.get(key);
            if(object!=null){
                //从缓存中获得数据,如果缓存中有直接返回
                return GraceJSONResult.ok(object);
            }else{
                //如果缓存中没有数据,则需要从数据库中查询数据
                List<Industry> list= industryService.getTopIndustry();
                //将查询的数据存入缓存中
                redisUtil.set(key,list);
                //返回数据
                return GraceJSONResult.ok(list);
            }
        }
        return GraceJSONResult.errorMsg("没有权限访问");
    }

    @GetMapping("/backend/getTopList")
    @ApiOperation(value = "获得一级行业分类的信息")
    public GraceJSONResult getTopListIndustry(){
        //验证当前登录的用户是否是后台管理员,如果是才能返回
        String s = JwtInterceptor.adminUserIds.get();
        if(StrUtil.isNotBlank(s)) {
            return GraceJSONResult.ok(industryService.getTopIndustry());
        }
        return GraceJSONResult.errorMsg("没有权限访问");
    }

    @GetMapping("/backend/childrenList")
    @ApiOperation(value = "获得行业分类下的子行业分类的信息")
    public GraceJSONResult childrenListIndustry(String fatherId){
        //验证当前登录的用户是否是后台管理员,如果是才能返回
        String s = JwtInterceptor.adminUserIds.get();
        if(StrUtil.isNotBlank(s)) {
            LambdaQueryWrapper<Industry> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Industry::getFatherId, fatherId);
            queryWrapper.orderByAsc(Industry::getSort);
            return GraceJSONResult.ok(industryService.list(queryWrapper));
        }
        return GraceJSONResult.errorMsg("没有权限访问");
    }

    @PostMapping("/backend/save")
    @ApiOperation(value="添加行业分类信息")
    public GraceJSONResult saveIndustry(@RequestBody IndustryAddForm form) {
        String s = JwtInterceptor.adminUserIds.get();
        if(StrUtil.isNotBlank(s)) {
            Industry industry = new Industry();
            BeanUtil.copyProperties(form, industry);
            setIndustry(industry);
            boolean flag=industryService.save(industry);
            if(flag) {
                //增量更新
                if (industry.getLevel() == 1) {
                    industryRBloomFilter.add(industry.getId());
                }
            }
            return GraceJSONResult.ok(flag);
        }
        return GraceJSONResult.errorMsg("没有权限访问");
    }

    @PostMapping("/backend/update")
    @ApiOperation(value="修改行业分类信息")
    public GraceJSONResult updateIndustry(@RequestBody IndustryUpdateForm form){
        String s = JwtInterceptor.adminUserIds.get();
        if(StrUtil.isNotBlank(s)) {
            LambdaUpdateWrapper<Industry> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Industry::getId, form.getId());
            updateWrapper.set(Industry::getName, form.getName());
            updateWrapper.set(Industry::getSort, form.getSort());
            return GraceJSONResult.ok(industryService.update(updateWrapper));
        }
        return GraceJSONResult.errorMsg("没有权限访问");
    }

    @DeleteMapping("/backend/delete")
    @ApiOperation(value = "删除行业分类信息")
    public GraceJSONResult deleteIndustry(String id){
        String s = JwtInterceptor.adminUserIds.get();
        if(StrUtil.isNotBlank(s)) {
            //判断行业分类下是否有子行业分类,如果没有则可以删除,否则不可以删除
            LambdaQueryWrapper<Industry> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Industry::getFatherId, id);
            if(industryService.count(queryWrapper) > 0){
                return GraceJSONResult.errorMsg("该行业分类下还有子行业分类,不能删除");
            }
            return GraceJSONResult.ok(industryService.removeById(id));
        }
        return GraceJSONResult.errorMsg("没有权限访问");
    }


    /**
     * 设置新增行业分类的层级信息
     */
    private void setIndustry(Industry industry){
        //1 如果父级行业分类id为空则抛出异常
        String fatherId = industry.getFatherId();
        if(StrUtil.isBlank(fatherId)){
            GraceException.display(ResponseStatusEnum.INDUSTRY_ERROR1);
        }
        //如果父级行业分类id为0,当前行业分类应该是顶级行业分类
        if(fatherId.equals("0")){
            industry.setLevel(1);
            industry.setIsLeaf((short)0);
            return;
        }
        //根据父级行业分类id查询父级行业分类如果为空 则抛出异常
        Industry fatherIndustry = industryService.getById(fatherId);
        if(fatherIndustry == null){
            GraceException.display(ResponseStatusEnum.INDUSTRY_ERROR1);
        }
        //2 如果父级行业分类是顶级行业分类,新增的行业分类就是二级行业分类
        if(fatherIndustry.getLevel().equals(1)){
            industry.setLevel(2);
            industry.setIsLeaf((short)0);
        }else if(fatherIndustry.getLevel().equals(2)){
            //3 如果父级行业分类是二级分类,新增的行业分类就是三级行业分类
            industry.setLevel(3);
            industry.setIsLeaf((short)1);
        }else{
            //4 如果父级行业分类是三级行业分类,则抛出异常(行业分类最多是三级分类)
            GraceException.display(ResponseStatusEnum.INDUSTRY_ERROR2);
        }
    }
}
